#include "header.h"

// 字符串分割 -- 用冒号和空格分割字符串
vector<string> splitStr(string s) {
  vector<string> res;
  string temp;
  for (int i = 0; i < s.size(); ++i) {
    if (s[i] != ' ' && s[i] != ':') temp += s[i];
    if (s[i] == ' ' || s[i] == ':' || i == s.size() - 1) {
      res.push_back(temp);
      temp = "";
    }
  }
  return res;
}

// 导入文件 并确定编码方式
void importTrainData(string path) {
  // 打开文件
  std::ifstream file_in(path, std::ios::in);
  if (!file_in.is_open()) {  // 打开失败
    cout << "#failed to open the file" << endl;
  }
  // -------- 文件格式 --------
  // attributes_num:4
  // attribute1:rain sunny cloudy
  // ...
  // attributeN:A B C
  // target_attribute:sport
  // 1:attribute1 attribute2 attribute3 ... attributeN True
  // 2:attribute1 attribute2 attribute3 ... attributeN False
  // ...
  // M:attribute1 attribute2 attribute3 ... attributeN True
  // eof
  // --------------------------

  // 1.读取一共有多少个特征
  {
    string firstLine;
    getline(file_in, firstLine);
    firstLine = firstLine.substr(strlen("attributes_num:"));
    table.resize(stoi(firstLine));
  }

  // 2.读取每个特征的取值
  for (int i = 0; i < table.size(); ++i) {
    // 读取一行
    string attribute;
    getline(file_in, attribute);
    // 分割字符串
    vector<string> splitLine = splitStr(attribute);
    // 第一项是特征名称
    attributes.push_back(splitLine[0]);
    // 后面的是特征取值
    for (int j = 1; j < splitLine.size(); ++j) {
      table[i].push_back(splitLine[j]);
    }
  }

  // 3.读取目标特征
  getline(file_in, target);
  target = target.substr(strlen("target attribute:"));

  // 4.读取每一个例子，并编码
  while (!file_in.eof()) {
    // 读取一行
    string value_line, temp_code;
    getline(file_in, value_line);
    // 处理这一行
    // 先分割
    vector<string> splitLine = splitStr(value_line);
    // 舍弃标号项，从下标[1]开始
    for (int i = 1; i < splitLine.size() - 1; ++i) {
      // 初始化追加编码，第i-1个特征有几个取值，就初始化为几个0
      string add_code = string(table[i - 1].size(), '0');
      // 该例子在本特征的取值是table中的第几个，就将第几位置1
      for (int j = 0; j < table[i - 1].size(); ++j) {
        if (splitLine[i] == table[i - 1][j]) {
          add_code[j] = '1';
          break;
        }
      }
      // 最后一位只能是Yes或者No
      // 追加代码
      temp_code += add_code;
    }
    temp_code += splitLine.back() == "Yes" ? '1' : '0';
    train_codes.push_back(temp_code);  // 这一行的结果
  }
  file_in.close();
}

// 根据编码解析字符串
string decode(string code) {
  string res;     // 返回结果
  int start = 0;  // 截取字符串开启位置
  // 每个特征分别解析
  for (int i = 0; i < table.size(); ++i) {
    // 截取每个特征
    string c_attr = code.substr(start, table[i].size());
    start += table[i].size();  // 更新截取字符串开始位置
    string add_res = "";       // 追加字符串
    // 解析每个属性
    for (int j = 0; j < c_attr.size(); ++j) {
      if (c_attr[j] == '1') {  // 是1说明有效
        // 不为空就需要析取
        if (add_res.size() != 0) add_res += " or ";
        // 添加元素
        add_res += "(" + table[i][j] + ")";
      }
    }
    // 不为空就要合取
    if(res.size() != 0) res += "\n    and ";
    res += "[" + attributes[i] + " = " + add_res + "]";
  }
  res = "IF {" + res + "\n  } \n# THEN " + target + " = " + (code.back() == '1' ? "(Yes)" : "(No)");
  return res;
}
